package com.qust.encryptionAndDecryption;


import com.qust.encryptionAndDecryption.enDecryption.AbstractEnDecryptionWithKeyPair;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Properties;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class KeyPair implements Serializable{

    private String publicKey;
    private String privateKey;

    /**
     * 用于生成keyPair并且保存到指定位置,保存的密钥会被password对称加密,请务必保存password
     *
     * @param encryptionAlgorithms
     * @param savePath
     * @param password
     * @return
     */
    public static KeyPair generateKeyPair(Class<? extends IEnDecryption> encryptionAlgorithms, String savePath, String password) {
        AbstractEnDecryptionWithKeyPair enDecryption = null;
        try {
            enDecryption = (AbstractEnDecryptionWithKeyPair) encryptionAlgorithms.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        KeyPair keyPair = enDecryption.generateKeyPair();
        try {
            keyPair.saveKey(savePath, password);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return keyPair;
    }

    public static KeyPair generateKeyPair(Class<? extends IEnDecryption> encryptionAlgorithms,String password){
        AbstractEnDecryptionWithKeyPair enDecryption = null;
        try {
            enDecryption = (AbstractEnDecryptionWithKeyPair) encryptionAlgorithms.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        KeyPair keyPair = enDecryption.generateKeyPair();

        try {
            keyPair.setPrivateKey(SymmetricEncryption.encrypt(keyPair.privateKey,password));
            keyPair.setPublicKey(SymmetricEncryption.encrypt(keyPair.publicKey,password));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return keyPair;
    }

    public void loadKey(String path, String password) throws Exception {
        Properties properties = new Properties();
        File file = new File(path);
        properties.load(new FileReader(file));
        this.privateKey = SymmetricEncryption.decrypt(properties.getProperty("privateKey"), password);
        this.publicKey = SymmetricEncryption.decrypt(properties.getProperty("publicKey"), password);
    }

    public void saveKey(String path, String password) throws IOException {
        Properties properties = new Properties();

        try {
            properties.setProperty("publicKey", SymmetricEncryption.encrypt(this.publicKey, password));
            properties.setProperty("privateKey", SymmetricEncryption.encrypt(this.privateKey, password));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        properties.store(Files.newOutputStream(Paths.get(path)), "key");
    }

    public void loadKey(String enPublicKey,String enPrivateKey,String password){
        try {
            this.publicKey = SymmetricEncryption.decrypt(enPublicKey,password);
            this.privateKey = SymmetricEncryption.decrypt(enPrivateKey,password);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


}
